import instance from './intercept'
import { ElMessage } from 'element-plus'
import { env } from '@/utils'
import { header, _ } from '@/utils'
import { confirm } from '@/utils'
import { useRouter } from 'vue-router'
import { respUtil } from '@/utils/response'
import * as FileSaver from 'file-saver'

const headersDefault = {
  ContentType: 'application/json;charset=UTF-8'
}

const request = (
  { baseURL = env.API_DOMAIN, headers = headersDefault, method, url, data, params, responseType }: AxiosType.Request,
  alterErr = true
): Promise<AxiosType.Response> => {
  return new Promise((resolve, reject) => {
    Object.assign(headers, header.getAuthorization())
    instance({ baseURL, headers, method, url, params, data, responseType })
      .then(async resp => {
        // status >= 200 && status < 300 满足这个条件都会进入then
        if (resp.status === 200) {
          // 正常返回
          if (!resp.data.skipResolve) {
            resolve({
              status: resp.status,
              statusText: resp.statusText,
              origin: resp.data,
              success: resp.data.success,
              message: resp.data?.message,
              data: resp.data?.data
            })
          }
        } else {
          // 错误返回
          const msg = resp.data?.message || url + '请求失败'
          errHandler(alterErr, resp.status, msg)
          reject({
            status: resp.status,
            statusText: resp.statusText,
            origin: resp.data,
            success: false,
            message: msg,
            data: resp.data?.data
          })
        }
      })
      .catch(err => {
        const msg = err?.data?.message || err?.message || url + '请求失败'
        errHandler(alterErr, err.status, msg)
        reject({
          status: err.status,
          statusText: err?.data?.message || err?.message,
          origin: err?.data,
          success: false,
          message: msg,
          data: err?.data?.data
        })
      })
  })
}

const errHandler = (alterErr: boolean, status: number, msg: string) => {
  if (alterErr) {
    if (status === 401) {
      // 认证失败, 重新登录
      confirm(`${msg}, 是否重新登录`, () => {
        const router = useRouter()
        router.push({ name: 'Logout' })
      })
    } else {
      ElMessage.error(msg)
    }
  }
}

const post = (
  { baseURL, headers, url, data, params, responseType }: AxiosType.Request,
  alterErr = true
): Promise<AxiosType.Response> => {
  return request({ baseURL, headers, method: 'post', url, data, params, responseType }, alterErr)
}

const get = (
  { baseURL, headers, url, data, params, responseType }: AxiosType.Request,
  alterErr = true
): Promise<AxiosType.Response> => {
  return request({ baseURL, headers, method: 'get', url, data, params, responseType }, alterErr)
}

const getPage = (
  { baseURL, headers, url, data, params, responseType }: AxiosType.Request,
  page: AxiosType.Pagination,
  alterErr = true
): Promise<AxiosType.Response> => {
  const newParams = <{ [key: string]: any }>{ pageNum: page.pageNum, pageSize: page.pageSize, export: page.export }
  if (!_.isEmpty(page.filter)) {
    const filter: any = {}
    for (const key in page.filter) {
      const val = page.filter[key]
      if (val instanceof Array) {
        filter[key] = JSON.stringify(val) // qs.stringify(val, { arrayFormat: 'comma' })
      } else {
        filter[key] = val
      }
    }
    newParams['filter'] = filter
  }
  if (!_.isEmpty(page.sort)) {
    let sortText = ''
    for (const col in page.sort) {
      let order = page.sort[col] as string
      if (order === 'descending') {
        order = 'desc'
      } else if (order === 'ascending') {
        order = 'asc'
      } else {
        order = 'asc'
      }
      sortText += `,${col} ${order}`
    }
    if (sortText) {
      newParams['sort'] = sortText.slice(1) //as unknown as object
    }
  }
  if (params) {
    newParams['params'] = params
  }
  if (page.export) {
    //分页参数中存在下载参数时,需要转换反馈类型，axios再response拦截中自动完成下载保存，不弹出错误
    responseType = 'blob'
  }
  return request({ baseURL, headers, method: 'get', url, data, params: newParams, responseType }, alterErr)
}

const download = ({
  baseURL = env.API_DOMAIN,
  headers = headersDefault,
  method = 'get',
  url,
  data,
  params
}: AxiosType.Request): Promise<AxiosType.Response> => {
  return new Promise(() => {
    Object.assign(headers, header.getAuthorization())
    instance({ baseURL, headers, method, url, params, data, responseType: 'blob' })
      .then(async resp => {
        if (resp.status === 200) {
          // 正常返回
          FileSaver.saveAs(resp.data, respUtil.getFileName(resp))
        } else {
          // 错误返回
          const msg = resp.data?.message || url + '请求失败'
          errHandler(true, resp.status, msg)
        }
      })
      .catch(err => {
        const msg = err?.data?.message || err?.message || url + '请求失败'
        errHandler(true, err.status, msg)
      })
  })
}

export { get, getPage, post, download }
